-
Notifications
You must be signed in to change notification settings - Fork 11.6k
[12.x] Add @maybe
Blade directive for conditional HTML attributes
#57235
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: 12.x
Are you sure you want to change the base?
Conversation
To me, the naming is not intuitive. I would call it |
I appreciate the feedback, but I'll leave the naming to Taylor. |
It'd be fine with |
Good one! One problem is the naming, I think |
I updated the naming section of the PR description. |
Thanks a lot 👍🏻 |
I think this should mirror
|
It is different in the sense that the For this use case here it makes it longer by 6 chars for the majority of situations where we have one data attribute. Don't really like it because the reason for the PR is to make things less verbose. That said, I'll have a look if we can support both. Edit: Happy to implement. For now I'll leave it to Taylor to decide first. {{-- Attributes: 1 --}}
<a @if($link->title) title="{{ $link->title }} @endif">
<a @maybe('title', $link->title)>
<a @maybe(['title' => $link->title])>
{{-- Attributes: 2 --}}
<a @if($link->title) title="{{ $link->title }} @endif" @if($link->rel) rel="{{ $link->rel }} @endif>
<a @maybe('title', $link->title) @maybe('rel', $link->rel)>
<a @maybe(['title' => $link->title, 'rel' => $link->rel])>
{{-- Attributes: 3 --}}
<a @if($link->title) title="{{ $link->title }} @endif" @if($link->rel) rel="{{ $link->rel }} @endif @if($link->clickId) data-tracker="{{ $link->clickId }} @endif">
<a @maybe('title', $link->title) @maybe('rel', $link->rel) @maybe('data-tracker', $link->clickId)>
<a @maybe(['title' => $link->title, 'rel' => $link->rel, 'data-tracker' => $link->clickId])> |
fyi, previous unsuccessful attempt at |
Similar. Mine is minus the complexity. Though, apparently high demand for a solution. |
I tried using This directive is quite valid. It could be expanded to include conditions like the |
I haven't dug deep into how this renders attributes, but I would expect the following to happen for these different attribute types. [
'crossorigin', // crossorigin
'data-persistent-across-pages' => 'YES', // data-persistent-across-pages="YES"
'remove-me' => false, // [removed]
'keep-me' => true, // keep-me
'null' => null, // [removed]
'empty-string' => '', // empty-string=""
'spaced-string' => ' ', // empty-string=" "
'zero' => 0, // zero="0"
'one' => 1, // zero="1"
]; <div
crossorigin
data-persistent-across-pages="YES"
keep-me
empty-string=""
spaced-string=" "
zero="0"
one="1"
/> This will keep it inline with how Vite handles attribute types and values. |
See arbitrary attributes in #43442 for more on these decisions. |
Hey Tim! I already read that in your comment to the PR linked above. But I kindly disagree. Personally I don't care what Vite does, what I care about is how I can add my own attributes in a non-verbose way. This PR seeks to handle the majority case we deal with every single day, not to be "aligned" with the Differences:
As I mentioned in my PR description, I would name this Both concepts are valid, but they cannot be merged in one (one wants to render false, one doesn't). Hence, what you are asking for is unfortunately nothing for this PR. 🙏 |
Appreciate you pushing back, @NickSdot! Always appreciated. To clarify, when I say Vite, I mean what we do in Laravel itself. Having different attribute rendering mechanics for two Laravel features seems like a footgun. But even taking the stand that we don't want to be inline with Laravel's attribute handling in the Vite space, I would still push back on the current rendering proposal. If nothing else, we should respect HTML itself. It explicitly mentions that ![]() |
I think my brain goes to tooling like jQuery when I see that we don't render empty strings and whitespace only strings. I probably need to think on that some more to come up with a compelling argument as my brain is deep in other stuff right now. None of this is a hill I wanna die on, btw. Just sharing a perspective and prior art in Laravel related to the feature to ensure we keep the framework cohesive when and where it makes sense. |
@timacdonald well, as I mentioned above, there is no way to satisfy two completely contrary concepts in one solution. Below I make a point why both are valid (+ spec conform) and why we need two mechanisms.
I knew that this will be the next argument. :) For the follwing reasons I need to push back again: 1) There are more than one relevant spec here. The ARIA spec for instance. Accessibility APIs expect explicit tokens. E.g:
2) Only valid for presence indicators (boolean attributes) What you are quoting is a separate concept with explicit behaviour. This, however, does not mean that I cannot use true/false in enumerated attributes (next section after the one on your screenshot: 2.3.3 Keywords and enumerated attributes). True/False are not forbidden values for enumerated attributes. We can do whatever we want, just cannot expect "boolean attributes" behaviour from it. To bring a simple example; you will agree that the folowing is neater foo.active = foo.active === 'true' ? 'false' : 'true'; than if (foo.hasAttribute('data-active')) {
foo.removeAttribute('data-active');
} else {
foo.setAttribute('data-active', '');
} Enumerated attributes allow us excactly that. And here we are also back to the previous point: ARIA attributes are enumerated attributes, not boolean ones. Both ways are HTML spec conform, even if we ignore that ARIA is a separate spec. 3) Third Party Expectations I am all for following specs. And I also have proven above that we are aligned with the spec. However, I still would like to throw in third party stuff. If a third party expects explicit
Yes, again, I don't object. Both concepts have their place. That's why we need two solutions for it. I believe we shouldn't try too hard to unify something that cannot be unified. It's like in the real world, we have a Slotted screwdriver and a Phillips screwdriver. Both aren't footguns, but solutions for different problems. 4) Last but not least You get the point: this is not only for custom data attributes.
Unfortunately, it (subjectively) feels like Taylor tends to close PRs when you hop in with objections. So if your objections are not fully thougt out... it's demotivating to be closed just because. No offense, of course! ❤️ I hope my arguments above are compelling enough to "book a win" here. |
No offense taken. It is my job to offer opinions here and there. Sorry if I've put you off here or on other PRs. I can see utility in a feature of this shape. FWIW, I hope some form of this gets merged. |
No, it's also not like that. Wasn't put off myself. So far you luckily been supportive to all my PRs. Sorry if I didn't express myself clear enough. 🙏 |
Awesome! |
I fully agree with @timacdonald and would rather see a single |
Adding to @willrowe's comment, the @attrs([
'aria-hidden' => $hidden ? 'true' : 'false',
'aria-expanded' => $expanded ? 'true' : 'false',
]) One can easily add a helper to their code base if wanted. Or just use @attr([
// json_encode will output booleans, numbers and null as a unquoted strings
'aria-hidden' => json_encode($hidden),
'aria-expanded' => json_encode($expanded),
]) But attribute toggling, as @timacdonald described, would be very awkward to accomplish with the current proposal. Also, calling the directive Mind that Blade's directives can also be used for non-HTML content, like markdown emails and Envoy tasks. I'd prefer, if added, for it to be called something like If different behavior due to Insert "Why not both?" meme here We could add a A |
This is Blade. Just saying. Y'all keep discussing things that this PR doesn't seek to solve. As we now already know there must be two different solutions because both concepts are diametrical to each other. This isn't "tailored" to one persons requirements, this is the majority use case. We all set title and rel attributes all the time. The alternative examples proposed above are hilarious. You realise that they are longer than writing the actual control flows this PR attempts to get rid off? About naming, I repeat, I leave that to Taylor. Guys, keep on bike shedding unrelated stuff instead of working on a complementing PR to add the other missing piece. I am sure that's how we will get good things! ✌️❤️ Edit: Edit 2:
|
Of course not. Those would be covered in the behavior everyone would expect a With sane rendering rules that follow the HTML spec, minus
Sure, mate. It is such an odd case it got a custom directive, a wrapper class, and a section on docs. https://laravel.com/docs/12.x/blade#rendering-json
Yes, it is. Or at least when one prioritizes The gripe is not on the value of the directive, as I, and I am sure others who commented out, like the proposed shorthand syntax in general. The gripe is on the proposed esoteric rendering rules. This argument doesn't make any sense on the But whatever, you do you. Good luck with your PR. I like the idea, just not the oddities, such as treating booleans as strings (which is perplexing). If not merged, consider publishing it as a package. I am sure many other developers would benefit from it for Have a nice day =) |
I answered the HTML spec question above in detail. This is spec conform. Read up enumeration attributes instead of ignoring it and liking comments which also got it wrong. Enumeration example from ARIA: Enumeration example from app: These have nothing to do with boolean attributes. Unfortunately, I cannot do more to help you to understand the difference.
Thanks for making the argument for getting this merged. And yet you don't want to see it merged. Because it isn't tailored to your use case? ;) I wish you the same! |
I do want to see it merged. Just not with such esoteric rendering rules. I find the syntax great: <a href="..." @attr('title', $title)>{{ $label }}</a> Where the The proposed syntax is very handy. Just not your particular use case for rendering attribute values in such a manner no one would expect.
Not my use case. HTML attributes spec. Imagine someone using Web Components opening issue after issue as they expect boolean attributes to behave conforming to the spec. Enumeration attributes are another spec suitable to specific use cases. It is not the general use case. And as such, IMO, it could be subject to a future addition, as I believe the general use case would benefit more developers. Or even provided by a 3rd-party package. I am sorry. I won't spend more of my time trying to help you bring this addition to the framework. I wish you the best luck. |
BooleansI promise I am not stubborn for the sake of it. I, however, cannot at all see what the added value of the following would be:
Why would we do that? It doesn't safe anything. Value-less attributes, aka boolean attributes per HTML spec, aren't what this PR is trying to solve. Like, if I'd need an actual boolean attribute, I'd go with a normal The whole promise of the directive I propose here is to pass values through to make verbosity go away. As in:
There we actually move the needle. But now we are even talking about adding extra helpers which would make writing a simple attribute more awkward than it is now. Mind you, we only talk about this because we consider booleans important in this directive even though the directive would not make anything shorter or better for boolean attributes. OpinionI can think back and forth and take everything mentioned here honestly into account and still think this directive, as is, works sensible and how we mostly need it every day. Naming
Well, that's ironically why @taylorotwell, perhaps we could go one better and meme-ify this by calling it Or should we call it Others
I cannot come up with one. Most go the verbose way as in
Vue & Svelte are cool, too. However, I don't like how they handle empty strings because it doesn't make sense for things like Edit: Both, Vue and Svelte, render the small subset of standard HTML attributes as per spec. The playground links doen't make that clear. However, this does not affect every non-standard boolean attributes which outnumber the standard attributes. Holistic Alternative
I believe boolean attributes make this more complicated as it should be -- for literally zero value added. This directive is not made for actual boolean attribute behaviour, which is different from all other HTML attributes. So perhaps to have a Looking at everything discussed, perhaps the following is what could cover everything?
The Enum and Bool is exactly what they are called in the HTML spec. But, again, no strong feelings about naming (anyway, please note how they all have 4 chars; banger!) from my side; but they should be short. I also have no strong feelings on how Negation Operator AlternativeOne more option is the following. @attr('foo', true) -> foo="true"
@attr('!foo', true) -> foo
@attr('foo', false) -> foo="false"
@attr('!foo', false) -> nothing This would be a special toggle for boolean value behaviour. We are used to the logical negation operator "!" in PHP. So, why not? It's a compromise with the least added chars. It takes everyones arguments into account and allows for both use case brought up here (if I didn't miss anything), without dismissing one side with "yours should be more verbose" or adding a new helper method. It also would help to not maintain an exceptions list. cc'ing the people with concerns: @timacdonald @rodrigopedra @willrowe Edits after feedback:
|
The main reason I want an <x-component @if($condition) boolean-attribute @endif /> Because I want to use this with Blade components, I would like for it to handle the attribute values consistently with how the component attribute bag does, which I outlined previously. |
I've been avoiding hopping in this PR, but I think I have to at this point to voice my support for the comments from: and against @NickSdot's position. I think the original goal of this PR was to solely to solve a verbosity issue, which is great. But along the way we discovered other issues it can (and should) solve, like cleaner boolean attributes, and better Blade component support. While the OP is correct, we can use simple <x-card
@if($condition) disabled @endif
></x-card>
<x-card
{{ $condition ? 'disabled' : '' }}
></x-card> Both of these components will throw compilation errors. I have a related issue open at #57123. If @timacdonald's render matrix were used, and possibly some minor work were done on the component compiler, we could get this feature working for Blade components, allowing them to be more versatile and be used in situations they couldn't before. I, for one, think we CAN have a single unified directive that solves all these problems, and I think the correct answer was already proposed by @rodrigopedra. For any of the special types:
we force the calling code to explicitly state it wants a string. <div
@attr('title', 'My Title')
@attr('checked', true)
@attr('disabled', false)
@attr('selected', null)
@attr('data-boolean', true)
@attr('data-boolean-string', true ? 'true' : '')
@attr('data-empty-string', '')
@attr('data-dont-show-empty-string', '' ?: false)
@attr('data-whitespace-string', ' ')
@attr('data-dont-show-whitespace-string, trim(' ') ? ' ' : false)
@attr('aria-hidden', true ? 'true' : false)
@attr('minlength', 0)
@attr('maxlength', 1)
></div> <div
title="My Title"
<!--disabled-->
checked
<!--selected-->
data-boolean
data-boolean-string="true"
data-empty-string=""
<!--data-dont-show-empty-string-->
data-whitespace-string=" "
<!--data-dont-show-whitespace-string-->
aria-hidden="true"
minlength="0"
maxlength="1"
></div> The beauty of the render matrix proposed by @timacdonald and the suggestion by @rodrigopedra is it gives the calling code FULL control over how the actual HTML is rendered, and allows us to correctly render both boolean, enumerated, and string attributes 100% correctly according to spec. The tradeoff is slightly more verbose code when we have to deal with these special types, but I think the versatility we gain is definitely worth it. |
@NickSdot cc'ed me, and I understood it as a request for comments. So, for those who are willing to read it all, please forgive me in advance for the lengthy response.
It is already clear the original intent is not to address boolean attributes. But at this point I'd assume it would be clear a PR comment section is a place Regarding enumerated attributes, the HTML spec states:
The key here is the "some attributes", which implies they are a finite set. Reference: https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#enumerated-attribute In other words, other than ARIA attributes, which follow their own spec, the HTML spec For example, the
Reference: https://html.spec.whatwg.org/#contenteditable I picked Handling the "output a boolean as a string" case by default to address just 4 cases listed in the spec seems to me an overkill. Especially when for all of them the "missing value default state" is Also, there are 33 boolean attributes in the specs, and it would be unfeasible and impractical to add a custom directive to each one, versus only 4 enumerated attributes that expect a "boolean as a string" among their valid values. Reference: https://html.spec.whatwg.org/multipage/indices.html#attributes-3 When using ARIA attributes, I don't think it would be a hassle to either use a helper to stringify a boolean (either a custom one or MDN also has a glossary entry on enumerated attributes with two interesting notes:
and
References:
Enumerated attributes, much like enums in most languages, have a previously known set of values. Also, the HTML spec does not make a provision for user-defined custom enumerated attributes. As noted by the MDN reference and also on the HTML spec, the DOM treats known enumerated attributes according to their definition on the specs. Including reflection when using the DOM. In contrast, a user can define custom web elements and register them to the DOM. I am not aware of a mechanism to register custom user-defined enumerated attributes. Unlike custom elements, I couldn't find a way to tell the DOM of them. Of course one can, and should be able to, use Mind that the spec does not provision Actually the spec states this about custom data attributes:
Within an example block:
And later
In other words, it is up to the developer to parse the value of these attributes from strings to any meaningful values. So it makes little sense, at least to me, to handle the "booleans as strings" case before handling boolean attributes. Reference: https://html.spec.whatwg.org/multipage/dom.html#custom-data-attribute That is why I am suggesting the directive to treat boolean attributes first and add a helper to handle the cases where a user would want the values to be stringified. The helper could also be useful when a user needs to stringify a boolean value in other places, such as JSON Resource: <?php
namespace App\Http\Resources;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class PostResource extends JsonResource
{
public function toArray(Request $request): array
{
return [
'id' => $this->resource->id,
'title' => $this->resource->title,
'contents' => $this->resource->contents,
// the helper name is open for suggestions
'is_archived' => stringify($this->resource->is_archived),
];
}
} Moving forward, using your very example arguing that you want a streamlined way to do things: <a href="#" @if($title) title="{{ $title }}" @endif>Link</a>
vs
<a href="#" @maybe('title', $title)>Link</a> If the value of the The value of the Another argument I would like to address is:
I would say that using this is even neater: foo.toggleAttribute('data-active'); As it uses a widely available feature across browsers. And does not depend on Reference: https://developer.mozilla.org/en-US/docs/Web/API/Element/toggleAttribute It is clear you are frustrated by the suggestions that diverge from your initial proposal. And as you agree, there won't be a one-size-fits-all solution. My suggestion to add both a directive and a helper was to try to accommodate a solution that works for both cases concerned in the comments section of this PR. Mind that future cases can be brought up by users on issues if this PR is merged, and that the maintainers would need to decide on how to accommodate valid use cases without breaking what is being discussed here. I guess we could consider these solutions:
Again, I like the addition of the new directive, and I don't have any personal gripes with anyone involved in the discussion. My comments are aimed to enrich the proposal and bring the best value both for the users and maintainers. |
@rodrigopedra while I agree with the overall sentiment of the previous comment, I also don't think we need to compromise with multiple directives and a helper. I think the single directive ( Would love to see any examples from people where they think this approach either wouldn't work completely, or would be less than ideal before we start complicating the solution. |
@browner12 I agree. At first I had solution no. 2 as the first one, but at the end I changed orders to try to accommodate a middle-ground solution. My preference is for a single directive that handles falsy values as they would be handled when using the The only 4 enumerated attributes that take It would also cover the 33 boolean attributes in the spec that don't already have dedicated directives, and nor should, but could benefit from the new directive. For example, the Also, as custom data attributes are meant to be used by the site's administrator, per the spec, one could also expect them to behave as boolean attributes, just checking for their presence. Boolean attributes on user-defined attributes are as a special case, as are using For these custom data attributes, or ARIA attributes, which a user could want to use |
Since when are we mixing x-component syntax with @-syntax? |
What's your response to that, for example, Vue and Svelte rendering regarding booleans is exactly how I propose it here? |
If I'm understanding your question correctly, we've been mixing directives into Blade components for at least 3 years. You can see here in the blame: we make special accommodations for some directives, and also specifically for FYI, you don't need to "Quote Reply" an entire comment. Makes the whole chain a little harder to read. We can usually pick up on context, and will ask for clarification if needed. |
@NickSdot I was typing this response when your comment appeared. I was curious to verify how the aforementioned Svelte and Vue playgrounds would handle boolean attributes. As @NickSdot just tested for a custom Links:
The results are:
There is a difference in the Svelte results for the Maybe it was an oversight, or they had an update in the meanwhile. But that doesn't change the overall results. The gist is that boolean attributes are handled by both parsers based on the value's And the user-defined |
Vue does not appear to be rendering exactly as you proposed. Vue appears to be doing additional logic under the hood so it does correctly handle boolean HTML attributes by completely omitting the attribute when the value is https://vuejs.org/guide/essentials/template-syntax#boolean-attributes This is something that we could do, but the extra maintenance of trying to stay up to date with the HTML spec does not seem worth it. |
Fun fact: What initially brought me into this PR and made me suggest Blade::directive('datetime', function (string $varName) {
return '<?php echo $__data[' . $varName . '] ? ' . $varName . ' : null; ?>';
});
// …
view('my-view', ['foo' => 'bar', 'disabled' => true]); <button @flag('disabled')>Click me, {{ $foo }}</button> |
Well, that is not a very representative metric in itself and rather distorting one actually. Just a small fraction of the community actively engages in discussions, so staying away from discussions can have a thousand different reasons than disagreement. On the other side, we have highly experienced community members like @timacdonald and @rodrigopedra who probably know the framework inside out. Not that that makes any of us better or right about this, more to disprove your point.
One alternative to addressing both not having to have multiple directives as well as supporting multiple different notations might be the following: enum BladeAttributeSpec
{
case Html;
case WaiAria;
case Data;
case Js;
// …
}
Blade::directive('attr', function (string $name, mixed $value, BladeAttributeSpec $spec) {
$attrRenderer = Blade::getAttributeRenderer($spec);
return $attrRenderer->render($name, $value);
}); |
This is only correct if we talk about the subset of standard boolean attributes.
You are right. I was still on my phone. Corrected.
Well, it's not that the spec rapidly changes. We could do that of course. But note, this also doesn't account for non-standard boolean attributes.
Also only correct for the subset of standard attributes. So yeah, if this is the concern you two have, we could make exceptions for the few standard attributes to align with the behaviour above. But let me add one more proposal. How about the following? @attr('foo', true) -> foo="true"
@attr('!foo', true) -> foo
@attr('foo', false) -> foo="false"
@attr('!foo', false) -> nothing
This would be a special toggle for boolean value behaviour. We are used to the logical negation operator |
I forgot that you brought up flag. If it would be decided to have a multi-directive approach as I suggested above, |
@NickSdot can you add an example or 2 of where you think our proposal would either not work or be less than ideal? |
Sure. But what proposal? You mean this?
It's not ideal because it defeats the goal of the PR. Making things less verbose by auto-passing.
What I propose is not only shorter by the amount of chars we see here, but by the actual condition which the directive I propose takes care of internally with it's sensible defaults I described in the matrix in the PR description. All three of you ask to add at least 18 characters to every single enum attribute that needs true/false, to make the actual boolean attributes case (which this directive isn't made for; we have boolean directives and
Could you add an example or 2 of where you think all 3 of my proposals would either not work or be less than ideal? |
This is literally a solved problem in Blade components as I mentioned here. And it has nothing to do with this PR. ![]() The same is true for non-boolean attributes in Blade components btw. So, really not sure how it is related to this PR and also not sure why you would want to nullify the problem this very PR tries to solve. cc @browner12 who came here for the same reason. |
Thanks for sharing an example. So to be clear, your position is our proposal doesn't make anything impossible, but makes it less than ideal because it makes things more verbose in a subset of the use cases. Yes I have some examples, thanks for asking. There are 4 values that we disagree on the rendering of:
Given the following examples: <div
@attr('disabled', false)
@attr('disabled, true)
@attr('data-custom', '')
@attr('data-custom', ' ')
></div> and your generated output: <div
disabled="false"
disabled="true"
<!-- missing data-custom=""-->
<!-- missing data-custom=" "-->
></div> your proposal would make generating valid HTML boolean attributes and empty string values impossible with this directive. I know you have suggested the So I think if we boil it down, the trade off is as follows:
I hope this is a succinct and thorough summary of both opinions. Given these tradeoffs, I am of the opinion that I will sacrifice fewer characters in the following cases:
for the ability for this directive to be able to generate all valid HTML attributes. I believe this gives us a good base. Automatic handling of the special cases to decrease the verbosity could be added either via automatic detection (increased maintenance) or a 3rd optional parameter. |
It literally defeats the purpose of this PR. It can be straight closed then.
No. I also proposed a
No. Not in a "subset" of cases. The actual boolean arttibutes are the subset; so subset that they have their very own spec.
Well, me and 14 others are of different opinion.
No. That's not the only solution. I proposed:
You conveniently ignored both, without any acknowledgement or argument why either is bad. You also ignored my hint that "automatic detecion" would only apply to standard HTML attributes. Personally, I think A) a third parameter is less nice than "!". B) Taylor doesn't like boolean flags in methods; why would it here be better than having multiple directives. I don't understand why all three of you solely make arguments in an "either this or that directive" way. We can have both. Or three. Or four. No one of you made an argument why what I propose here should not exist apart from that you have different requirements to how it should work. So, let what you want to have be another directive. I am cool with that since I opened the PR. So again, why can't this directive -- that covers the absolute majority of standard cases -- AND one that does what you propose exist? Here, again a slimmed down version of what I posted above to make it super clear for you:
As you see I don't even care about
So, could we now please acknowledge that me and 15 others have a demand for this very directive I propose here and that hence the answer cannot be that we get in what you want but skip what we want? I propose the following next steps:
Table as Markdown
How does that sound? |
HTML spec is too broad. While others can be functionally like |
Agree on this.
This defeats the goal of the PR because it would too long. Multiple directives solve that. |
It's not about what either 4 or 15 people want. It's about what's best and most maintainable for the framework as a whole. I'm making my argument for what I think is best, and you make your argument for what you think is best. Then the BDFL comes in, passes judgement, and we all move on with our lives. Of course 2 directives could exist. Or 3, or 4, or 10. But that adds a maintenance cost. If we choose to pay it, great. I've made my case for a single directive I believe best covers the use cases. |
Now, that looks smart 😲 Very intriguing solution 🤔 I'm usually not in favor of multiple information within one string, but on one hand, it's pretty common in the framework already, and on the other, it's both quite short and addresses some problems from this discussion fairly well 👍🏻 |
About the
I disagree with this take. From what I can see, the last PR that generated this level of discussion was at least 6 years ago. This PR is already in the top 10 most-commented PRs in the entire framework. That tells me the feature itself is valuable and people actually care about it. |
I'd be totally down to that—good point 👍🏻
And it's a discussion needed to make a PR result in well-implemented features 👍🏻 |
Personally, I still believe the boolean case as the opposition here wants it is the minority; we use it less. I'd keep it as is and don't invert. However, I'd not die from it being inverted. If it would be decided to invert, I'd to say this would be more nice: @attr('foo=', true) -> foo="true"
@attr('foo', true) -> foo
@attr('foo=', false) -> foo="false"
@attr('foo', false) -> nothing Basically it says, if the |
Makes sense 👍🏻 |
Since we start complicating things. 😂😂😂 |
This PR adds a new
@maybe
directive that conditionally renders HTML attributes with values, complementing the existing boolean attribute directives like@checked
,@selected
,@disabled
,@required
, and@readonly
.Problem
While we have directives for boolean attributes, we still need verbose
@if ... @endif
blocks for attributes with values:We cannot keep adding specific directives for every possible attribute, so we need a dynamic solution.
Solution
The
@maybe
directive renders an attribute with a value only when the value is notnull
, not an empty string, and not whitespace-only:Before/After
Behaviour Matrix
The directive intentionally differs from a simple
@if()
check by treating0
andfalse
as valid values, since these are common in data attributes for counts, flags, and boolean states.'foo'
data-attribute="foo"
0
data-attribute="0"
false
data-attribute="false"
true
data-attribute="true"
''
null
' '
Naming
I considered several alternatives:
@when
(too generic, likely better for other future use cases),@flag
(implies boolean values only, whereas this handles strings, numbers, bools),@attribute
and@optional
(too long),@attr
and@set
(don’t make the conditional nature clear).@has
was tempting as it reads well: “has$title
, then rendertitle
”. However, the parameter order would need reversing to@has($title, 'title')
, which breaks the pattern of other Blade directives where the static value comes first.@opt
is appealingly terse but perhaps too cryptic.@maybe
has the right balance. It’s short, clearly conditional, and reads naturally with the attribute name first: “maybe render title if$title
”.